package com.hongshu.idle.service.sys.impl;

import cn.hutool.core.util.ObjectUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.BulkResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hongshu.common.core.constant.Constantss;
import com.hongshu.common.core.constant.NoteConstant;
import com.hongshu.common.core.domain.R;
import com.hongshu.common.core.enums.AuditStatusEnum;
import com.hongshu.common.core.enums.ProductEnum;
import com.hongshu.common.core.enums.ResultCodeEnum;
import com.hongshu.common.core.exception.HongshuException;
import com.hongshu.common.core.global.SysConf;
import com.hongshu.common.core.utils.*;
import com.hongshu.common.core.validator.ValidatorUtil;
import com.hongshu.idle.domain.Query;
import com.hongshu.idle.domain.entity.IdleCategory;
import com.hongshu.idle.domain.entity.IdleProduct;
import com.hongshu.idle.domain.entity.WebUser;
import com.hongshu.idle.domain.vo.IdleProductVO;
import com.hongshu.idle.mapper.idle.IdleProductMapper;
import com.hongshu.idle.mapper.sys.SysIdleCategoryMapper;
import com.hongshu.idle.mapper.web.WebUserMapper;
import com.hongshu.idle.service.idle.IIdleEsProductService;
import com.hongshu.idle.service.sys.ISysIdleProductService;
import com.hongshu.system.api.RemoteFileService;
import com.hongshu.system.api.domain.SysFile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 闲宝信息 服务层处理
 *
 * @author hongshu
 */
@Slf4j
@Service
public class SysIdleProductServiceImpl implements ISysIdleProductService {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private IIdleEsProductService esProductService;
    @Autowired
    private WebUserMapper userMapper;
    @Autowired
    private IdleProductMapper productMapper;
    @Autowired
    private SysIdleCategoryMapper idleCategoryMapper;
    //    @Autowired
//    private IOssService ossService;
    @Autowired
    private RemoteFileService remoteFileService;
    @Autowired
    private ElasticsearchClient elasticsearchClient;


    /**
     * 查询笔记信息集合
     */
    @Override
    public List<IdleProduct> getAllProductList() {
        QueryWrapper<IdleProduct> qw = new QueryWrapper<>();
        // 审核通过的笔记
        qw.lambda().like(IdleProduct::getAuditStatus, 1);
        return productMapper.selectList(qw);
    }

    /**
     * 查询笔记信息集合
     *
     * @param query 笔记信息
     */
    @Override
    public List<IdleProduct> selectProductList(Query query) {
        QueryWrapper<IdleProduct> qw = new QueryWrapper<>();
        qw.lambda().like(ValidatorUtil.isNotNull(query.getTitle()), IdleProduct::getTitle, query.getTitle());
        qw.lambda().like(ValidatorUtil.isNotNull(query.getUid()), IdleProduct::getUid, query.getUid());
        qw.lambda().like(ValidatorUtil.isNotNull(query.get("type")), IdleProduct::getType, query.get("type"));
        qw.lambda().eq(ValidatorUtil.isNotNull(query.get("auditStatus")), IdleProduct::getAuditStatus, query.get("auditStatus"));
        qw.lambda().eq(ValidatorUtil.isNotNull(query.get("pid")), IdleProduct::getCpid, query.get("pid"));
        qw.lambda().eq(ValidatorUtil.isNotNull(query.get("uid")), IdleProduct::getUid, query.get("uid"));
        // 处理 beginTime 和 endTime
        String beginTimeStr = (String) query.get("params[beginTime]");
        String endTimeStr = (String) query.get("params[endTime]");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (beginTimeStr != null) {
            try {
                // 将字符串转为 Date
                Date beginTime = sdf.parse(beginTimeStr);
                // 添加大于等于条件
                qw.lambda().ge(IdleProduct::getCreateTime, beginTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (endTimeStr != null) {
            try {
                Date endTime = sdf.parse(endTimeStr);
                // 确保 endTime 是当天的结束时间（23:59:59）
                endTime = new Date(endTime.getTime() + 1000 * 60 * 60 * 24 - 1);
                // 添加小于等于条件
                qw.lambda().le(IdleProduct::getCreateTime, endTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 排序
        qw.lambda().orderByDesc(IdleProduct::getUpdateTime);
        return productMapper.selectList(qw);
    }

    /**
     * 获取未审核笔记列表
     */
    @Override
    public List<IdleProduct> selectUnAuditProductList(Query query) {
        QueryWrapper<IdleProduct> qw = new QueryWrapper<>();
        qw.lambda().like(ValidatorUtil.isNotNull(query.getTitle()), IdleProduct::getTitle, query.getTitle());
        qw.lambda().like(ValidatorUtil.isNotNull(query.getUid()), IdleProduct::getUid, query.getUid());
        qw.lambda().like(ValidatorUtil.isNotNull(query.get("type")), IdleProduct::getType, query.get("type"));
        qw.lambda().like(ValidatorUtil.isNull(query.get("auditStatus")), IdleProduct::getAuditStatus, 0);
        // 处理 beginTime 和 endTime
        String beginTimeStr = (String) query.get("params[beginTime]");
        String endTimeStr = (String) query.get("params[endTime]");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (beginTimeStr != null) {
            try {
                // 将字符串转为 Date
                Date beginTime = sdf.parse(beginTimeStr);
                // 添加大于等于条件
                qw.lambda().ge(IdleProduct::getCreateTime, beginTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (endTimeStr != null) {
            try {
                Date endTime = sdf.parse(endTimeStr);
                // 确保 endTime 是当天的结束时间（23:59:59）
                endTime = new Date(endTime.getTime() + 1000 * 60 * 60 * 24 - 1);
                // 添加小于等于条件
                qw.lambda().le(IdleProduct::getCreateTime, endTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 排序
        qw.lambda().orderByDesc(IdleProduct::getCreateTime);
        return productMapper.selectList(qw);
    }

    /**
     * 通过笔记ID查询笔记信息
     *
     * @param id 笔记ID
     */
    @Override
    public IdleProduct selectProductById(Long id) {
        return productMapper.selectById(id);
    }

    /**
     * 新增笔记信息
     *
     * @param product 笔记信息
     */
    @Override
    public int insertProduct(IdleProduct product, MultipartFile file) {
        // 上传头像
        if (ObjectUtils.isNotEmpty(file)) {
//            String productCover = ossService.upload(file);
            R<SysFile> upload = remoteFileService.upload(file);
            String productCover = upload.getData().getUrl();
            product.setCover(productCover);
        }
        product.setCreator("System");
        product.setCreateTime(new Date());
        product.setUpdateTime(new Date());
        return productMapper.insert(product);
    }

    /**
     * 修改保存笔记信息
     *
     * @param product 笔记信息
     */
    @Override
    public int updateProduct(IdleProduct product, MultipartFile file) {
        // 上传头像
        if (ObjectUtils.isNotEmpty(file)) {
//            String productCover = ossService.upload(file);
            R<SysFile> upload = remoteFileService.upload(file);
            String productCover = upload.getData().getUrl();
            product.setCover(productCover);
        }
        product.setUpdater("System");
        product.setUpdateTime(new Date());
        return productMapper.updateById(product);
    }

    /**
     * 批量删除笔记信息
     *
     * @param ids 需要删除的笔记ID
     */
    @Override
    public int deleteProductByIds(Long[] ids) {
        List<Long> longs = Arrays.asList(ids);
        for (Long id : ids) {
            IdleProduct product = productMapper.selectById(id);
            if (ValidatorUtil.isNull(product)) {
                log.info("笔记不存在:{}", id);
                longs.remove(id);
            }
        }
        return productMapper.deleteBatchIds(longs);
    }

    /**
     * 审核管理
     *
     * @param productId 笔记ID
     * @param auditType 审核状态
     */
    @Override
    public void auditProduct(String productId, String auditType) {
        IdleProduct product = productMapper.selectOne(new QueryWrapper<IdleProduct>().eq("id", productId));
        if (ObjectUtil.isEmpty(product)) {
            throw new HongshuException(ResultCodeEnum.FAIL);
        }
        // 通过：1
        if ("pass".equals(auditType)) {
            product.setAuditStatus(AuditStatusEnum.PASS.getCode());
            // 审核通过，笔记添加到ES中
            WebUser user = userMapper.selectById(product.getUid());
            IdleCategory parentCategory = idleCategoryMapper.selectByCpid(product.getCpid());
            IdleProductVO productVO = ConvertUtils.sourceToTarget(product, IdleProductVO.class);
            if (StringUtils.isNotBlank(product.getCid()) && !"0".equals(product.getCid())) {
                IdleCategory category = idleCategoryMapper.selectByPid(product.getCid());
                productVO.setCategoryName(category.getTitle());
            }
            productVO.setUsername(user.getUsername()).setAvatar(user.getAvatar()).setCategoryParentName(parentCategory.getTitle()).setTime(System.currentTimeMillis());
            esProductService.addProduct(productVO);
        }
        // 拒绝：2
        if ("reject".equals(auditType)) {
            product.setAuditStatus(AuditStatusEnum.REJECT.getCode());
        }
        product.setUpdateTime(new Date());
        productMapper.updateById(product);
    }

    /**
     * 批量增加商品
     */
    @Override
    public void addProductBulkData() {
        List<IdleProduct> productList = productMapper.selectList(new QueryWrapper<IdleProduct>().eq("status", 0));
        List<IdleProductVO> productVOList = DozerUtil.convertor(productList, IdleProductVO.class);
        for (IdleProductVO productVO : productVOList) {
            WebUser user = userMapper.selectOne(new QueryWrapper<WebUser>().eq("id", productVO.getUid()));
            if (user != null) {
                productVO.setAvatar(user.getAvatar());
                productVO.setUsername(user.getUsername());
            }
        }
        try {
            List<BulkOperation> result = new ArrayList<>();
            for (IdleProductVO productVO : productVOList) {
                result.add(new BulkOperation.Builder().create(d -> d.document(productVO).id(productVO.getId()).index(NoteConstant.PRODUCT_INDEX)).build());
            }
            BulkResponse bulkResponse = elasticsearchClient.bulk(e -> e.index(NoteConstant.PRODUCT_INDEX).operations(result));
            log.info("createResponse.result{}", bulkResponse.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 清空笔记
     */
    @Override
    public void delProductBulkData() {
        try {
            // 检查索引是否存在
            if (elasticsearchClient.indices().exists(existsRequest -> existsRequest.index(NoteConstant.PRODUCT_INDEX)).value()) {
                // 删除索引
                DeleteIndexRequest deleteIndexRequest = DeleteIndexRequest.of(builder -> builder.index(NoteConstant.PRODUCT_INDEX));
                elasticsearchClient.indices().delete(deleteIndexRequest);
                log.info("成功删除索引: {}", NoteConstant.PRODUCT_INDEX);
            } else {
                log.info("索引 {} 不存在，无需删除", NoteConstant.PRODUCT_INDEX);
            }
            // 重新创建索引
            CreateIndexRequest createIndexRequest = CreateIndexRequest.of(builder -> builder.index(NoteConstant.PRODUCT_INDEX));
            elasticsearchClient.indices().create(createIndexRequest);
            log.info("成功创建索引: {}", NoteConstant.PRODUCT_INDEX);
        } catch (Exception e) {
            log.error("Error occurred while deleting and recreating index: {}", NoteConstant.PRODUCT_INDEX, e);
        }
    }

    /**
     * 重置
     */
    @Override
    public void refreshProductData() {
        this.delProductBulkData();
        this.addProductBulkData();
    }

    @Override
    public List<Map<String, Object>> getProductCountByCategory() {
        try {
            // 1. 获取分类统计数据
            List<Map<String, Object>> categoryStats = productMapper.getProductByCategory();
            if (categoryStats.isEmpty()) {
                return Collections.emptyList();
            }

            // 2. 提取分类ID并获取分类数量
            Map<String, Integer> categoryCountMap = categoryStats.stream().collect(Collectors.toMap(item -> String.valueOf(item.get("cpid")), item -> Optional.ofNullable(item.get(SysConf.COUNT)).map(num -> ((Number) num).intValue()).orElse(0)));

            // 3. 批量查询分类信息
            List<IdleCategory> categories = idleCategoryMapper.selectBatchIds(categoryCountMap.keySet());
            if (categories.isEmpty()) {
                return Collections.emptyList();
            }

            // 4. 组装最终结果
            return categories.stream().filter(category -> StringUtilss.isNotEmpty(category.getTitle())).map(category -> {
                String categoryId = String.valueOf(category.getId());
                Map<String, Object> result = new HashMap<>(3);
                result.put(SysConf.BLOG_SORT_UID, categoryId);
                result.put(SysConf.NAME, category.getTitle());
                result.put(SysConf.VALUE, categoryCountMap.getOrDefault(categoryId, 0));
                return result;
            }).collect(Collectors.toList());

        } catch (Exception e) {
            log.error("获取分类商品统计失败", e);
            return Collections.emptyList();
        }
    }

    @Override
    public Integer getProductCount() {
        QueryWrapper<IdleProduct> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq(BaseSQLConf.STATUS, EStatus.ENABLE);
        return Math.toIntExact(productMapper.selectCount(queryWrapper));
    }

    @Override
    public List<Map<String, Object>> getProductCountByType() {
        List<Map<String, Object>> productByType = productMapper.getProductCountByType();
        List<Map<String, Object>> resultList = new ArrayList<>();

        // 统计现有数据
        Map<String, Integer> typeCountMap = new HashMap<>();
        for (Map<String, Object> item : productByType) {
            String productType = String.valueOf(item.get("product_type"));
            Number count = (Number) item.get(SysConf.COUNT);
            typeCountMap.put(productType, count != null ? count.intValue() : 0);
        }

        // 遍历所有笔记类型，确保包含所有类型的统计
        for (ProductEnum type : ProductEnum.values()) {
            Map<String, Object> resultItem = new HashMap<>();
            resultItem.put(SysConf.BLOG_SORT_UID, type.getCode());
            resultItem.put(SysConf.NAME, type.getDesc());
            resultItem.put(SysConf.VALUE, typeCountMap.getOrDefault(type.getCode(), 0));
            resultList.add(resultItem);
        }
        return resultList;
    }

    @Override
    public Map<String, Object> getProductContributeCount() {
        // 从Redis中获取博客分类下包含的博客数量
//        String jsonMap = redisUtil.get(RedisConf.DASHBOARD + Constantss.SYMBOL_COLON + RedisConf.BLOG_CONTRIBUTE_COUNT);
//        if (StringUtilss.isNotEmpty(jsonMap)) {
//            Map<String, Object> resultMap = JsonUtils.jsonToMap(jsonMap);
//            return resultMap;
//        }

        // 获取今天结束时间
        String endTime = DateUtilss.getNowTime();
        // 获取365天前的日期
        Date temp = DateUtilss.getDate(endTime, -365);
        String startTime = DateUtilss.dateTimeToStr(temp);
        List<Map<String, Object>> productContributeMap = productMapper.getProductContributeCount(startTime, endTime);
        List<String> dateList = DateUtilss.getDayBetweenDates(startTime, endTime);
        Map<String, Object> dateMap = new HashMap<>();
        for (Map<String, Object> itemMap : productContributeMap) {
            dateMap.put(itemMap.get("DATE").toString(), itemMap.get("COUNT"));
        }

        List<List<Object>> resultList = new ArrayList<>();
        for (String item : dateList) {
            int count = 0;
            if (dateMap.get(item) != null) {
                count = Integer.parseInt(dateMap.get(item).toString());
            }
            List<Object> objectList = new ArrayList<>();
            objectList.add(item);
            objectList.add(count);
            resultList.add(objectList);
        }

        Map<String, Object> resultMap = new HashMap<>(Constantss.NUM_TWO);
        List<String> contributeDateList = new ArrayList<>();
        contributeDateList.add(startTime);
        contributeDateList.add(endTime);
        resultMap.put(SysConf.CONTRIBUTE_DATE, contributeDateList);
        resultMap.put(SysConf.GOODS_CONTRIBUTE_COUNT, resultList);
        // 将 全年商品贡献度 存入到Redis【过期时间2小时】
//        redisUtil.setEx(RedisConf.DASHBOARD + Constantss.SYMBOL_COLON + RedisConf.BLOG_CONTRIBUTE_COUNT, JsonUtils.objectToJson(resultMap), 2, TimeUnit.HOURS);
        return resultMap;
    }
}
